home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 19 / Mac Magazin and MacEasy Magazine CD - Issue 19.iso / Utilities / uae-0.4 / Source Code / xwin.c < prev   
Text File  |  1996-02-05  |  18KB  |  721 lines

  1.  /* 
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * X interface
  5.   * 
  6.   * Copyright 1995, 1996 Bernd Schmidt
  7.   * Copyright 1996 Ed Hanway, Andre Beck
  8.   */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <sys/time.h>
  14. #include <X11/Xlib.h>
  15. #include <X11/Xutil.h>
  16. #include <X11/keysym.h>
  17. #include <X11/cursorfont.h>
  18.  
  19. #ifndef DONT_WANT_SHM
  20. #include <sys/ipc.h>
  21. #include <sys/shm.h>
  22. #include <X11/extensions/XShm.h>
  23. #endif
  24.  
  25. #include "config.h"
  26. #include "amiga.h"
  27. #include "options.h"
  28. #include "memory.h"
  29. #include "custom.h"
  30. #include "newcpu.h"
  31. #include "xwin.h"
  32. #include "keyboard.h"
  33. #include "keybuf.h"
  34.  
  35. #ifdef LINUX_SVGALIB
  36. #error Compiling xwin.c, but LINUX_SVGALIB set. Re-edit "config.h".
  37. #endif
  38.  
  39. static Display *display;
  40. static int screen;
  41. static Window rootwin, mywin;
  42.  
  43. static GC whitegc,blackgc;
  44. static XColor black,white;
  45. static Colormap cmap;
  46.  
  47. static XImage *img;
  48. static Visual *vis;
  49. static XVisualInfo visualInfo;
  50. static int bitdepth;
  51. #ifndef DONT_WANT_SHM
  52. static XShmSegmentInfo shminfo;
  53. #endif
  54. static Cursor blankCursor, xhairCursor;
  55. static bool cursorOn;
  56.  
  57. #ifdef DONT_WANT_SHM
  58. static char pixel_buffer[3200];
  59. #endif
  60. static char *xlinestart;
  61. char *xlinebuffer;
  62. long int xcolors[4096];
  63.  
  64.  /* Keyboard and mouse */
  65.  
  66. static bool keystate[256];
  67.  
  68. bool buttonstate[3];
  69. int lastmx, lastmy;
  70. bool newmousecounters;
  71. static bool inwindow;
  72. const long int eventmask = (KeyPressMask|KeyReleaseMask|ButtonPressMask
  73.                 |ButtonReleaseMask|PointerMotionMask
  74.                 |FocusChangeMask|EnterWindowMask
  75.                 |LeaveWindowMask);
  76.  
  77. static bool next_line_double;
  78. static int next_line_pos = 0;
  79.  
  80. void flush_screen (void)
  81. {
  82. #ifndef DONT_WANT_SHM
  83.     if (next_line_pos > 0) {    
  84.     XShmPutImage(display, mywin, blackgc, img, 0, 0, 0, 0, 796, next_line_pos, 0);
  85.     XSync(display, 0);
  86.     next_line_pos = 0;
  87.     }
  88. #endif
  89. }
  90.  
  91. void prepare_line (int y, bool need_double)
  92. {
  93.     next_line_double = need_double;
  94.     next_line_pos = y;
  95.     
  96. #ifdef DONT_WANT_SHM
  97.     xlinebuffer = pixel_buffer;
  98. #else
  99.     xlinestart = xlinebuffer = img->data + y * img->bytes_per_line;
  100. #endif
  101. }
  102.  
  103. void flush_line(void)
  104. {
  105. #ifdef DONT_WANT_SHM
  106.     XPutImage(display, mywin, blackgc, img, 0, 0, 0, next_line_pos, 796, 1);
  107.     if (next_line_double)
  108.         XPutImage(display, mywin, blackgc, img, 0, 0, 0, next_line_pos+1, 796, 1);
  109. #else
  110.     if (use_fast_draw && next_line_double) {    
  111.         memcpy (xlinestart + img->bytes_per_line, xlinestart, img->bytes_per_line);
  112.     next_line_pos++; /* For flush_screen(). */
  113.     }
  114. #endif
  115. }
  116.  
  117. #ifndef INLINE_DRAWPIXEL
  118. void (*DrawPixel)(int, xcolnr);
  119.  
  120. static void DrawPixel16(int x, xcolnr col)
  121. {
  122.     *(short *)xlinebuffer = col;
  123.     xlinebuffer += 2;
  124. }
  125.  
  126. static void DrawPixel32(int x, xcolnr col)
  127. {
  128.     *(long *)xlinebuffer = col;
  129.     xlinebuffer += 4;
  130. }
  131.  
  132. static void DrawPixel8(int x, xcolnr col)
  133. {
  134.     *(char *)xlinebuffer = col;
  135.     xlinebuffer += 1;
  136. }
  137.  
  138. static void DrawPixelGeneric(int x, xcolnr col)
  139. {
  140. #ifdef DONT_WANT_SHM
  141.     XPutPixel(img, x, 0, col);
  142. #else
  143.     XPutPixel(img, x, next_line_pos, col);
  144.     if (next_line_double) {
  145.     XPutPixel(img, x, next_line_pos+1, col);
  146.     }
  147. #endif
  148. }
  149. #endif /* INLINE_DRAWPIXEL */
  150.  
  151. #ifndef DONT_WANT_SHM
  152. static void initShm(int depth)
  153. {
  154.     int scale = dont_want_aspect ? 1 : 2;
  155.     img = XShmCreateImage(display, vis, depth,
  156.               ZPixmap, 0, &shminfo, 800, (313-29) * scale);
  157.     
  158.     shminfo.shmid = shmget(IPC_PRIVATE, 512*1024*scale, IPC_CREAT|0777);
  159.     shminfo.shmaddr = img->data = (char *)shmat(shminfo.shmid, 0, 0);
  160.     shminfo.readOnly = False;
  161.     /* let the xserver attach */
  162.     XShmAttach(display, &shminfo);
  163.     /* NOW ! */
  164.     XSync(display,0);
  165.     /* now deleting means making it temporary */
  166.     shmctl(shminfo.shmid, IPC_RMID, 0);
  167.     
  168.     xlinestart = xlinebuffer = img->data;
  169. }
  170. #endif
  171.  
  172. static __inline__ int bitsInMask(unsigned long mask)
  173. {
  174.     /* count bits in mask */
  175.     int n = 0;
  176.     while(mask) {
  177.     n += mask&1;
  178.     mask >>= 1;
  179.     }
  180.     return n;
  181. }
  182.  
  183. static __inline__ int maskShift(unsigned long mask)
  184. {
  185.     /* determine how far mask is shifted */
  186.     int n = 0;
  187.     while(!(mask&1)) {
  188.     n++;
  189.     mask >>= 1;
  190.     }
  191.     return n;
  192. }
  193.  
  194. static __inline__ unsigned long doMask(int p, int bits, int shift)
  195. {
  196.     /* p is a value from 0 to 15 (Amiga color value)
  197.      * scale to 0..255, shift to align msb with mask, and apply mask */
  198.  
  199.     unsigned long val = p * 0x11111111UL;
  200.     val >>= (32 - bits);
  201.     val <<= shift;
  202.  
  203.     return val;
  204. }
  205.  
  206. static void InitXColors(void)
  207. {
  208. #ifdef INLINE_DRAWPIXEL
  209.  
  210. #ifdef X_8BIT_SCREEN
  211.     if (visualInfo.depth != 8) {    
  212.         fprintf(stderr, "Unsupported bit depth (%d)\n", visualInfo.depth);
  213.     exit(1);
  214.     }
  215. #endif
  216.  
  217. #ifdef X_16BIT_SCREEN
  218.     if (visualInfo.depth != 12 && visualInfo.depth != 16) {
  219.         fprintf(stderr, "Unsupported bit depth (%d)\n", visualInfo.depth);
  220.     exit(1);
  221.     }
  222. #endif
  223.  
  224. #else /* not INLINE_DRAWPIXEL */
  225.     DrawPixel = DrawPixelGeneric;
  226.  
  227.     if(use_fast_draw) {
  228.     /* this is probably a lot faster but makes nonportable assumptions
  229.      * about image format */
  230.     
  231.     switch(visualInfo.depth) {
  232.      case 12:
  233.         DrawPixel = DrawPixel16;
  234.         break;
  235.         
  236.      case 24:
  237.         DrawPixel = DrawPixel32;
  238.         break;
  239.  
  240.      case 16:
  241.         DrawPixel = DrawPixel16;
  242.         break;
  243.  
  244.      case 8:
  245.         DrawPixel = DrawPixel8;
  246.         break;
  247.  
  248.      default:
  249.         fprintf(stderr, "Unsupported bit depth (%d)\n", visualInfo.depth);
  250.         exit(1);
  251.     }
  252.     }
  253. #endif /* not INLINE_DRAWPIXEL */
  254.     
  255. #ifdef __cplusplus
  256.     switch(visualInfo.c_class) {
  257. #else
  258.     switch(visualInfo.class) {
  259. #endif
  260.      case TrueColor: 
  261.     {        
  262.         int red_bits = bitsInMask(visualInfo.red_mask);
  263.         int green_bits = bitsInMask(visualInfo.green_mask);
  264.         int blue_bits = bitsInMask(visualInfo.blue_mask);
  265.         int red_shift = maskShift(visualInfo.red_mask);
  266.         int green_shift = maskShift(visualInfo.green_mask);
  267.         int blue_shift = maskShift(visualInfo.blue_mask);
  268.         
  269.         int i;
  270.         for(i = 0; i < 4096; i++) {
  271.         int r = i >> 8;
  272.         int g = (i >> 4) & 0xF;
  273.         int b = i & 0xF;
  274.         xcolors[i] = (doMask(r, red_bits, red_shift) 
  275.                   | doMask(g, green_bits, green_shift) 
  276.                   | doMask(b, blue_bits, blue_shift));
  277.         }
  278.     }
  279.     break;
  280.  
  281.      case GrayScale:
  282.      case PseudoColor:
  283.     {
  284.         /* This is kind of kludgy...
  285.          * Try to allocate as many different colors as possible. */
  286.         int col;
  287.         int step = 16;
  288.         int allocated[4096];
  289.         memset(allocated,0,sizeof allocated);
  290.         
  291.         while ((step/=2) > 0) {
  292.         int r, g, b;
  293.         for(r=0; r<16; r += step) {
  294.             for(g=0; g<16; g += step) {
  295.             for(b=0; b<16; b += step) {
  296.                 int cnr = (r << 8) + (g << 4) + b;
  297.                 if (!allocated[cnr]) {
  298.                 XColor col;
  299.                 char str[10];
  300.                 sprintf(str, "rgb:%x/%x/%x", r,g,b);
  301.                 XParseColor(display,cmap,str,&col);
  302.                 if (XAllocColor(display,cmap,&col)) {                
  303.                     allocated[cnr] = true;
  304.                     xcolors[cnr] = col.pixel;
  305.                 } 
  306.                 }
  307.             }
  308.             }
  309.         }
  310.         }
  311.  
  312.         for(col = 0; col < 4096; col++) {
  313.         int cnr = col;
  314.         if (!allocated[cnr]) {
  315.             int r = cnr >> 8;
  316.             int g = (cnr >> 4) & 0xF;
  317.             int b = cnr & 0xF;
  318.             int maxd = 4096,best = 0;
  319.             int c2;
  320.             for(c2 = 0; c2 < 4096; c2++)
  321.                 if (allocated[c2]) {
  322.                 int r2 = c2 >> 8;
  323.                 int g2 = (c2 >> 4) & 0xF;
  324.                 int b2 = c2 & 0xF;
  325.                 int dist = abs(r2-r)*2 + abs(g2-g)*3 + abs(b2-b);
  326.                 if (dist < maxd) {
  327.                 maxd = dist;
  328.                 best = c2;
  329.                 }
  330.             }
  331.             cnr = best;
  332.         }
  333.         xcolors[col] = xcolors[cnr];
  334.         
  335.         }
  336.     }
  337.     break;
  338.     
  339.      default:
  340. #ifdef __cplusplus
  341.     fprintf(stderr, "Unsupported class (%d)\n", visualInfo.c_class);
  342. #else
  343.     fprintf(stderr, "Unsupported class (%d)\n", visualInfo.class);
  344. #endif
  345.     exit(1);
  346.     }
  347. }
  348.  
  349. void graphics_init(void)
  350. {
  351.     int i;
  352.     char *display_name = 0;
  353.     XSetWindowAttributes wattr;
  354.     int vscale = dont_want_aspect ? 1 : 2;
  355.  
  356.     display = XOpenDisplay(display_name);
  357.     if (display == 0)  {
  358.     fprintf(stderr, "Can't connect to X server %s\n", XDisplayName(display_name));
  359.     exit(-1);
  360.     }
  361.     screen = XDefaultScreen(display);
  362.     rootwin = XRootWindow(display,screen);
  363.  
  364.     /* try for a 12 bit visual first, then a 16 bit, then a 24 bit, then 8 bit */
  365.     if (XMatchVisualInfo(display, screen, 12, TrueColor, &visualInfo)) {
  366.     } else if (XMatchVisualInfo(display, screen, 16, TrueColor, &visualInfo)) {
  367.     } else if (XMatchVisualInfo(display, screen, 24, TrueColor, &visualInfo)) {
  368.     } else if (XMatchVisualInfo(display, screen, 8, PseudoColor, &visualInfo)) {
  369.       /* for our HP boxes */
  370.     } else if (XMatchVisualInfo(display, screen, 8, GrayScale, &visualInfo)) {
  371.     } else {
  372.     fprintf(stderr, "Can't obtain appropriate X visual\n");
  373.     exit(1);
  374.     }
  375.  
  376.     vis = visualInfo.visual;
  377.     bitdepth = visualInfo.depth;
  378.  
  379.     fprintf(stderr, "Using %d bit visual\n", bitdepth);
  380.  
  381.     cmap = XCreateColormap(display, rootwin, vis, AllocNone);
  382.     XParseColor(display, cmap, "#000000", &black);
  383.     if (!XAllocColor(display, cmap, &black))
  384.     fprintf(stderr, "Whoops??\n");
  385.     XParseColor(display, cmap, "#ffffff", &white);
  386.     if (!XAllocColor(display, cmap, &white))
  387.     fprintf(stderr, "Whoops??\n");
  388.  
  389.     wattr.event_mask = eventmask;
  390.     wattr.background_pixel = black.pixel;
  391.     wattr.backing_store = Always;
  392.     wattr.backing_planes = bitdepth;
  393.     wattr.border_pixmap = None;
  394.     wattr.border_pixel = black.pixel;
  395.     wattr.colormap = cmap;
  396.  
  397.     mywin = XCreateWindow(display,rootwin,0,0,796,vscale*(313-29),0,
  398.               bitdepth, InputOutput, vis,
  399.               CWEventMask|CWBackPixel|CWBorderPixel|CWBackingStore
  400.               |CWBackingPlanes|CWColormap,
  401.               &wattr);
  402.     XMapWindow(display,mywin);
  403.     
  404.     blankCursor = XCreatePixmapCursor(display,
  405.                       XCreatePixmap(display, mywin, 1, 1, 1),
  406.                       XCreatePixmap(display, mywin, 1, 1, 1), 
  407.                       &black, &white, 0, 0);
  408.     xhairCursor = XCreateFontCursor(display, XC_crosshair);
  409.  
  410.     whitegc = XCreateGC(display,mywin,0,0);
  411.     blackgc = XCreateGC(display,mywin,0,0);
  412.     
  413.     XSetForeground(display,blackgc,black.pixel);
  414.     XSetForeground(display,whitegc,white.pixel);
  415.  
  416. #ifdef DONT_WANT_SHM
  417.     img = XCreateImage(display, vis, bitdepth, ZPixmap, 0, pixel_buffer, 800, 
  418.                1, 32, 0);
  419. #else
  420.     initShm (bitdepth);
  421. #endif
  422.     InitXColors();
  423.     buttonstate[0] = buttonstate[1] = buttonstate[2] = false;
  424.     for(i=0; i<256; i++) keystate[i] = false;
  425.     
  426.     lastmx = lastmy = 0; newmousecounters = false; inwindow = false;
  427.     XDefineCursor(display, mywin, xhairCursor);
  428.     cursorOn = true;
  429. }
  430.  
  431. void graphics_leave(void)
  432. {
  433.     XAutoRepeatOn(display);
  434. }
  435.  
  436. /* Decode KeySyms. This function knows about all keys that are common 
  437.  * between different keyboard languages. */
  438. static int kc_decode (KeySym ks)
  439. {
  440.     switch (ks) {    
  441.      case XK_A: case XK_a: return AK_A;
  442.      case XK_B: case XK_b: return AK_B;
  443.      case XK_C: case XK_c: return AK_C;
  444.      case XK_D: case XK_d: return AK_D;
  445.      case XK_E: case XK_e: return AK_E;
  446.      case XK_F: case XK_f: return AK_F;
  447.      case XK_G: case XK_g: return AK_G;
  448.      case XK_H: case XK_h: return AK_H;
  449.      case XK_I: case XK_i: return AK_I;
  450.      case XK_J: case XK_j: return AK_J;
  451.      case XK_K: case XK_k: return AK_K;
  452.      case XK_L: case XK_l: return AK_L;
  453.      case XK_M: case XK_m: return AK_M;
  454.      case XK_N: case XK_n: return AK_N;
  455.      case XK_O: case XK_o: return AK_O;
  456.      case XK_P: case XK_p: return AK_P;
  457.      case XK_Q: case XK_q: return AK_Q;
  458.      case XK_R: case XK_r: return AK_R;
  459.      case XK_S: case XK_s: return AK_S;
  460.      case XK_T: case XK_t: return AK_T;
  461.      case XK_U: case XK_u: return AK_U;
  462.      case XK_V: case XK_v: return AK_V;
  463.      case XK_W: case XK_w: return AK_W;
  464.      case XK_X: case XK_x: return AK_X;
  465.     
  466.      case XK_0: return AK_0;
  467.      case XK_1: return AK_1;
  468.      case XK_2: return AK_2;
  469.      case XK_3: return AK_3;
  470.      case XK_4: return AK_4;
  471.      case XK_5: return AK_5;
  472.      case XK_6: return AK_6;
  473.      case XK_7: return AK_7;
  474.      case XK_8: return AK_8;
  475.      case XK_9: return AK_9;
  476.     
  477.      case XK_KP_0: return AK_NP0;
  478.      case XK_KP_1: return AK_NP1;
  479.      case XK_KP_2: return AK_NP2;
  480.      case XK_KP_3: return AK_NP3;
  481.      case XK_KP_4: return AK_NP4;
  482.      case XK_KP_5: return AK_NP5;
  483.      case XK_KP_6: return AK_NP6;
  484.      case XK_KP_7: return AK_NP7;
  485.      case XK_KP_8: return AK_NP8;
  486.      case XK_KP_9: return AK_NP9;
  487.     
  488.      case XK_F1: return AK_F1;
  489.      case XK_F2: return AK_F2;
  490.      case XK_F3: return AK_F3;
  491.      case XK_F4: return AK_F4;
  492.      case XK_F5: return AK_F5;
  493.      case XK_F6: return AK_F6;
  494.      case XK_F7: return AK_F7;
  495.      case XK_F8: return AK_F8;
  496.      case XK_F9: return AK_F9;
  497.      case XK_F10: return AK_F10;
  498.         
  499.      case XK_BackSpace: case XK_Delete: return AK_BS;
  500.      case XK_Control_L: return AK_CTRL;
  501.      case XK_Tab: return AK_TAB;
  502.      case XK_Alt_L: case XK_Meta_L: return AK_LALT;
  503.      case XK_Alt_R: case XK_Meta_R: return AK_RALT;
  504.      case XK_Return: return AK_RET;
  505.      case XK_space: return AK_SPC;
  506.      case XK_Shift_L: return AK_LSH;
  507.      case XK_Shift_R: return AK_RSH;
  508.      case XK_Escape: return AK_ESC;
  509.  
  510.      case XK_Up: return AK_UP;
  511.      case XK_Down: return AK_DN;
  512.      case XK_Left: return AK_LF;
  513.      case XK_Right: return AK_RT;
  514.     
  515.      case XK_F11: return AK_BACKSLASH;
  516.      case XK_F12: return AK_mousestuff;
  517.      case XK_Scroll_Lock: return AK_inhibit;
  518.  
  519. #ifdef XK_Page_Up /* These are missing occasionally */
  520.      case XK_Page_Up: return AK_RAMI;          /* PgUp mapped to right amiga */
  521.      case XK_Page_Down: return AK_LAMI;        /* PgDn mapped to left amiga */
  522. #endif
  523.     }
  524.     return -1;
  525. }
  526.  
  527. static int decode_us(KeySym ks)
  528. {
  529.     switch(ks) {    /* US specific */    
  530.      case XK_Y: case XK_y: return AK_Y;
  531.      case XK_Z: case XK_z: return AK_Z;
  532.      case XK_bracketleft: return AK_LBRACKET;
  533.      case XK_bracketright: return AK_RBRACKET;
  534.      case XK_comma: return AK_COMMA;
  535.      case XK_period: return AK_PERIOD;
  536.      case XK_slash: return AK_SLASH;
  537.      case XK_semicolon: return AK_SEMICOLON;
  538.      case XK_minus: return AK_MINUS;
  539.      case XK_equal: return AK_EQUAL;
  540.     /* this doesn't work: */
  541.      case XK_grave: return AK_QUOTE;
  542.     }
  543.  
  544.     return -1;
  545. }
  546.  
  547. static int decode_de(KeySym ks)
  548. {
  549.     switch(ks) {
  550.     /* DE specific */
  551.      case XK_Y: case XK_y: return AK_Z;
  552.      case XK_Z: case XK_z: return AK_Y;
  553.      case XK_Odiaeresis: case XK_odiaeresis: return AK_SEMICOLON;
  554.      case XK_Adiaeresis: case XK_adiaeresis: return AK_QUOTE;
  555.      case XK_Udiaeresis: case XK_udiaeresis: return AK_LBRACKET;
  556.      case XK_plus: case XK_asterisk: return AK_RBRACKET;
  557.      case XK_comma: return AK_COMMA;
  558.      case XK_period: return AK_PERIOD;
  559.      case XK_less: case XK_greater: return AK_LTGT;
  560.      case XK_numbersign: return AK_NUMBERSIGN;
  561.      case XK_ssharp: return AK_MINUS;
  562.      case XK_apostrophe: return AK_EQUAL;
  563.      case XK_asciicircum: return AK_00;
  564.      case XK_minus: return AK_SLASH;        
  565.     }
  566.  
  567.     return -1;
  568. }
  569.  
  570. static int keycode2amiga(XKeyEvent *event)
  571. {
  572.     KeySym ks;
  573.     int as;
  574.     int index = 0;
  575.     
  576.     do {
  577.     ks = XLookupKeysym(event, index);
  578.     as = kc_decode (ks);
  579.     
  580.     if (as == -1) {        
  581.         switch(keyboard_lang) {
  582.          case KBD_LANG_US:
  583.         as = decode_us(ks);
  584.         break;
  585.         
  586.          case KBD_LANG_DE:
  587.         as = decode_de(ks);
  588.         break;
  589.         
  590.          default:
  591.         as = -1;
  592.         break;
  593.         }
  594.     }
  595.     if(-1 != as)
  596.         return as;
  597.     index++;
  598.     } while (ks != NoSymbol);
  599.     return -1;
  600. }
  601.  
  602. static struct timeval lastMotionTime;
  603.  
  604. void handle_events(void)
  605. {
  606.     bool repeat;
  607.     newmousecounters = false;
  608.     do {
  609.     XEvent event;
  610.     if (!XCheckMaskEvent(display, eventmask, &event)) break;
  611.     repeat = false;
  612.     
  613.     switch(event.type) {
  614.      case KeyPress: {        
  615.          int kc = keycode2amiga((XKeyEvent *)&event);
  616.          if (kc == -1) break;
  617.          switch (kc) {
  618.           case AK_mousestuff:
  619. #if 0
  620.              if (keystate[AK_CTRL])
  621.              mousesetup();
  622.          else 
  623. #endif
  624.              togglemouse();
  625.          break;
  626.  
  627.           case AK_inhibit:
  628.          inhibit_frame ^= 1;
  629.          break;
  630.  
  631.           default:
  632.               if (!keystate[kc]) {
  633.              keystate[kc] = true;
  634.              record_key (kc << 1);
  635.          }
  636.          break;
  637.          }
  638.          break;
  639.      }
  640.      case KeyRelease: {         
  641.          int kc = keycode2amiga((XKeyEvent *)&event);
  642.          if (kc == -1) break;
  643.          keystate[kc] = false;
  644.          record_key ((kc << 1) | 1);
  645.          break;
  646.      }
  647.      case ButtonPress:
  648.         buttonstate[((XButtonEvent *)&event)->button-1] = true;
  649.         break;
  650.      case ButtonRelease:
  651.         buttonstate[((XButtonEvent *)&event)->button-1] = false;
  652.         break;
  653.      case EnterNotify:
  654.         newmousecounters = true;
  655.         lastmx = ((XCrossingEvent *)&event)->x;
  656.         lastmy = ((XCrossingEvent *)&event)->y;
  657.         repeat = true;
  658.         inwindow = true;
  659.         break;
  660.      case LeaveNotify:
  661.         inwindow = false;
  662.         repeat = true;
  663.         break;
  664.      case FocusIn:
  665.         XAutoRepeatOff(display);
  666.         repeat = true;
  667.         break;
  668.      case FocusOut:
  669.         XAutoRepeatOn(display);
  670.         repeat = true;
  671.         break;
  672.      case MotionNotify:
  673.         if (inwindow) {        
  674.         lastmx = ((XMotionEvent *)&event)->x;
  675.         lastmy = ((XMotionEvent *)&event)->y;
  676.         if(!cursorOn) {
  677.             XDefineCursor(display, mywin, xhairCursor);
  678.             cursorOn = true;
  679.         }
  680.         gettimeofday(&lastMotionTime, NULL);
  681.         }
  682.         repeat = true;
  683.         break;
  684.     }
  685.     } while (repeat);
  686.     
  687.     if(cursorOn) {
  688.     struct timeval now;
  689.     int diff;
  690.     gettimeofday(&now, NULL);
  691.     diff = (now.tv_sec - lastMotionTime.tv_sec) * 1000000 + 
  692.         (now.tv_usec - lastMotionTime.tv_usec);
  693.     if(diff > 1000000) {
  694.         XDefineCursor(display, mywin, blankCursor);
  695.         cursorOn = false;
  696.     }
  697.     }
  698.     
  699.     /* "Affengriff" */
  700.     if(keystate[AK_CTRL] && keystate[AK_LAMI] && keystate[AK_RAMI])
  701.         MC68000_reset();
  702. }
  703.  
  704. bool debuggable(void)
  705. {
  706.     return true;
  707. }
  708.  
  709. bool needmousehack(void)
  710. {
  711.     return true;
  712. }
  713.  
  714. void LED(int on)
  715. {
  716.     XKeyboardControl control;
  717.     control.led = 1; /* implementation defined */
  718.     control.led_mode = on ? LedModeOn : LedModeOff;
  719.     XChangeKeyboardControl(display, KBLed | KBLedMode, &control);
  720. }
  721.